package mrpanyu.guitool.base;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;

import mrpanyu.guitool.base.annotation.AnnotatedToolModel;
import mrpanyu.guitool.base.model.ToolModel;
import mrpanyu.guitool.base.util.ClassScanner;
import mrpanyu.guitool.base.view.cli.CliMultiTool;
import mrpanyu.guitool.base.view.cli.CliTool;
import mrpanyu.guitool.base.view.swing.GuiConfig;
import mrpanyu.guitool.base.view.swing.GuiMultiToolFrame;
import mrpanyu.guitool.base.view.swing.GuiToolFrame;

public class GuiToolRunner {

	public static void run(Class<?> annotatedToolModelClass, GuiConfig guiConfig, String[] args) {
		guiConfig = Optional.ofNullable(guiConfig).orElse(new GuiConfig());
		setScale(args, guiConfig);
		if (annotatedToolModelClass == null) {
			throw new IllegalArgumentException("annotatedToolModelClass cannot be null");
		}
		AnnotatedToolModel toolModel = new AnnotatedToolModel(annotatedToolModelClass);
		if (args != null && Arrays.asList(args).indexOf("-cli") >= 0) {
			CliTool cli = new CliTool(toolModel);
			cli.run();
		} else {
			GuiToolFrame frame = new GuiToolFrame(toolModel, guiConfig);
			frame.setVisible(true);
		}
	}

	public static void run(Class<?> annotatedToolModelClass, String[] args) {
		run(annotatedToolModelClass, null, args);
	}

	public static void run(List<Class<?>> annotatedToolModelClasses, GuiConfig guiConfig, String[] args) {
		guiConfig = Optional.ofNullable(guiConfig).orElse(new GuiConfig());
		setScale(args, guiConfig);
		if (annotatedToolModelClasses == null || annotatedToolModelClasses.isEmpty()) {
			throw new IllegalArgumentException("annotatedToolModelClasses cannot be null or empty");
		} else if (annotatedToolModelClasses.size() == 1) {
			run(annotatedToolModelClasses.get(0), guiConfig, args);
		} else {
			List<ToolModel> toolModels = new ArrayList<>();
			for (Class<?> tmc : annotatedToolModelClasses) {
				AnnotatedToolModel toolModel = new AnnotatedToolModel(tmc);
				toolModels.add(toolModel);
			}
			if (args != null && Arrays.asList(args).indexOf("-cli") >= 0) {
				CliMultiTool cli = new CliMultiTool(toolModels);
				cli.run();
			} else {
				GuiMultiToolFrame frame = new GuiMultiToolFrame(toolModels);
				frame.setVisible(true);
			}
		}
	}

	public static void run(List<Class<?>> annotatedToolModelClasses, String[] args) {
		run(annotatedToolModelClasses, null, args);
	}

	public static void run(String basePackage, GuiConfig guiConfig, String[] args) {
		List<Class<?>> annotatedToolModelClasses = ClassScanner.findClassesByAnnotation(basePackage, true,
				mrpanyu.guitool.base.annotation.ToolModel.class);
		if (annotatedToolModelClasses.isEmpty()) {
			throw new IllegalArgumentException(
					"No class found with annotation @ToolModel under package: " + basePackage);
		} else if (annotatedToolModelClasses.size() == 1) {
			run(annotatedToolModelClasses.get(0), guiConfig, args);
		} else {
			run(annotatedToolModelClasses, guiConfig, args);
		}
	}

	public static void run(String basePackage, String[] args) {
		run(basePackage, null, args);
	}

	private static void setScale(String[] args, GuiConfig guiConfig) {
		double scale = 1d;
		for (String arg : args) {
			if (arg.startsWith("scale=")) {
				scale = Double.parseDouble(arg.substring(6));
				break;
			}
		}
		// disable java9 auto scale
		System.setProperty("sun.java2d.uiScale", "1.0");
		System.setProperty("glass.win.uiScale", "100%");
		System.setProperty("prism.allowhidpi", "false");
		// set scale config
		guiConfig.scale(scale);
	}

}
